#ifndef _GAME_OBJECT_MANAGER_H_
#define _GAME_OBJECT_MANAGER_H_

//#include <string>
//#include <map>

#include "Ogre.h"

using namespace Ogre;

#include "GameObjTemplateMgr.h"
#include "GameCompTemplateMgr.h"
#include "GameSceneManager.h"
//#include "GameObject.h"

//#include "GameComponent.h"
//#include "GameComponentTemplate.h"
//#include "GameObjectTemplate.h"

//#include "CPlayer.h"
//#include "CCamera.h"
//#include <map>
//#include "GameComponent.h"

/*
class GameObjTemplateMgr;
class GameCompTemplateMgr;
class GameObject;
class GameComponent;
class GameComponentTemplate;
class GameObjectTemplate;
class ComponentTemplate;
class ObjectTemplate;
*/

enum {
	MOVE_MODE = 0,
	ROTATE_MODE = 1,
	SCALE_MODE = 2
};

//Config structure of the Game Object Manager
struct GOMConfig {

	unsigned int mode;

	std::string objectInHand;
	std::string objectSelected;
	
	bool isObjectSelected;
	bool isHoldingItem;
	
	bool isMovingObject;
	Vector3 axisToMove;

	std::string selectedMesh;

};
extern GOMConfig gom_config;

class GameObjectManager {
	//Component interface
public:
	GameObjectManager();
	~GameObjectManager();

	void loadGameObjectsFromXML(TiXmlElement* mElem);
	void saveGameObjectsToXML(TiXmlElement* mElem);
	void setAttribute(std::string name,std::string  value);

	void registerComponentTemplate(GameComponentTemplate *ctemp);
	void registerObjectTemplate(GameObjectTemplate *otemp);

	static GameObjectManager *getSingleton();
	
	std::map<const std::string, GameObject*> getGOs();
	
	int numComponents;
	
	int getNextCompIndex();
	//GameComponent* addComponent(const comp_id_type &id) {
	//	comp_id_type family = newComp->familyID();
	//	Component *oldComp = mComponents[family];
	//	mComponents[family] = newComp;
	//	return oldComp;
	//}
	GameObject* getGO(const obj_id_type &id);
	void deleteGO(const obj_id_type &id);
	void reloadGO(std::string goName);

	//GameObject* createObject(const obj_id_type &id);
	
	//You can create custom objects and insert them in the scene with this method
	GameObject* createCustomObject(GameObject*);

	//Object is created from the template list
	GameObject* createObjectFromTemplate(const obj_id_type &templateName,const obj_id_type &objectID); //std::string tName,
	
	
	void clearGameObjects();
	
	//CompVisual interface
	void update();
	void mouseButtonDownNotification(bool controledByGui,unsigned int button);
	void mouseButtonUpNotification(bool controledByGui,unsigned int button);
	void mouseMovedNotification(bool controledByGui,int x,int y);
	
	void updateObjectRotation();
	void updateObjectScaling();

	Ogre::Quaternion updateObjectYawMove();
	Ogre::Quaternion updateObjectPitchMove();
	Ogre::Quaternion updateObjectRollMove();

	void addCustomGO(std::string objName, bool isMesh,bool isLight,bool isRagdoll, std::string meshFileName, float xScale = 1.0f, float yScale = 1.0f, float zScale = 1.0f, float xPosition = 0.0f, float yPosition = 0.0f, float zPosition  = 0.0f);

	void updateObjectDecalPosition(Vector3 pos);
	void setVisibleObjectDecal(bool visible);
	void createDecals();

private:
	//static comp_id_type mFamilyID;
	//static comp_id_type mComponentID;
	static GameObjectManager *mInstance;
	
	SceneNode* objectDecalNode;

	static ObjTemplateMgr *mOTM;
	static CompTemplateMgr *mCTM;

	std::map<const std::string, GameObject*> mGOs; //Game objects collection
};

#endif
